﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Threading;

namespace Fractals
{
    public partial class Form1 : Form
    {
        private Simulator m_simulator;

        #region Properties

        public int ProgressBar
        { set { this.toolStripProgressBar1.Value = value; } }
        public string ToolStripStatus
        {
            set
            {
                this.toolStripStatusLabel1.Text = value;
                toolStripStatusLabel1.Invalidate();
                this.Update();
            }
        }

        #endregion

        public Form1()
        {
            InitializeComponent();

            // and a new Simulator that works on this bitmap
            m_simulator = new Simulator(interpolatedPictureBox1, (int)numericUpDownWidth.Value, (int)numericUpDownHeight.Value, this)
            {
                ParticleCount = (int)numericUpDown1.Value,
                ParticleMaxLifetime = (int)numericUpDown2.Value,
            };

            // set comboBoxes
            comboBox1.SelectedIndex = 0;
            comboBox2.SelectedIndex = 0;
            comboBox3.SelectedIndex = 0;
            comboBox4.SelectedIndex = 1;

            checkBox1.Checked = true;

            // get Interpolation modes and set them into the combobox
            var interpolmodes = System.Enum.GetValues(typeof(System.Drawing.Drawing2D.InterpolationMode))
                .OfType<System.Drawing.Drawing2D.InterpolationMode>()
                .Where(x => x.ToString() != "Invalid" && x.ToString() != "Default");
            comboBoxInterpolationModes.DataSource = interpolmodes.ToArray();

            //// set NN as default interpolation mode
            //comboBoxInterpolationModes.SelectedIndex = comboBoxInterpolationModes.FindString("Near");

            try
            {
                comboBoxInterpolationModes.SelectedIndex = comboBoxInterpolationModes.FindString("HighQualityBicubic");
            }
            catch (Exception)
            {
                comboBoxInterpolationModes.SelectedIndex = comboBoxInterpolationModes.FindString("Near");
            }
        }

        private void runSimulation(object sender, EventArgs e)
        {
            //var m_threadResult = BeginInvoke(new ThreadStart(() => m_simulator.simulate()));

            button1.Enabled = false;

            toolStripStatusLabel1.Text = "Simulating ...";
            toolStripStatusLabel1.Invalidate();
            this.Update();
            m_simulator.simulate();

            toolStripStatusLabel1.Text = "Loading Image ...";
            toolStripStatusLabel1.Invalidate();
            this.Update();
            interpolatedPictureBox1.Refresh();

            toolStripStatusLabel1.Text = "Done";
            toolStripStatusLabel1.Invalidate();
            this.Update();

            button1.Enabled = true;
            button2.Enabled = true;
        }

        private void saveImageToFile(object sender, EventArgs e)
        {
            Image image = m_simulator.Image;
            // Displays a SaveFileDialog so the user can save the Image
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "PNG Image|*.png|JPeg Image|*.jpg|Bitmap Image|*.bmp";
            saveFileDialog1.Title = "Save image to file";
            saveFileDialog1.ShowDialog();

            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {
                // Saves the Image via a FileStream created by the OpenFile method.
                System.IO.FileStream fs =
                   (System.IO.FileStream)saveFileDialog1.OpenFile();
                // Saves the Image in the appropriate ImageFormat based upon the
                // File type selected in the dialog box.
                // NOTE that the FilterIndex property is one-based.
                switch (saveFileDialog1.FilterIndex)
                {
                    case 1:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Png);
                        break;

                    case 2:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Jpeg);
                        break;

                    case 3:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Bmp);
                        break;
                }

                fs.Close();
            }
        }

        private void changeParticleCount(object sender, EventArgs e)
        {
            m_simulator.ParticleCount = (int)numericUpDown1.Value;
        }

        private void changeMaxIterations(object sender, EventArgs e)
        {
            m_simulator.ParticleMaxLifetime = (int)numericUpDown2.Value;
        }

        private void changeStartRegionType(object sender, EventArgs e)
        {
            m_simulator.StartRegionType = comboBox1.SelectedItem.ToString();
        }

        private void changeTargetRegionType(object sender, EventArgs e)
        {
            m_simulator.TargetRegionType = comboBox2.SelectedItem.ToString();
        }

        private void changeNeighborhoodMode(object sender, EventArgs e)
        {
            if (comboBox4.SelectedIndex == 0)
                m_simulator.NeighborhoodMode = false;
            else
                m_simulator.NeighborhoodMode = true;
        }

        private void resizeImage(object sender, EventArgs e)
        {
            m_simulator.Image = new Bitmap((int)numericUpDownWidth.Value, (int)numericUpDownHeight.Value, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        }

        private void changeVerboseMode(object sender, EventArgs e)
        {
            m_simulator.VerboseMode = checkBox2.Checked;
        }

        private void changeLiveUpdateMode(object sender, EventArgs e)
        {
            m_simulator.LiveUpdateMode = checkBox1.Checked;
        }

        private void changeShowTargetRegion(object sender, EventArgs e)
        {
            m_simulator.ShowTargetRegion = checkBox5.Checked;
        }

        private void changeShowStartRegion(object sender, EventArgs e)
        {
            m_simulator.ShowStartRegion = checkBox3.Checked;
        }

        private void changeInterpolationMode(object sender, EventArgs e)
        {
            // grab it
            var currentState = (System.Drawing.Drawing2D.InterpolationMode)Enum.Parse(typeof(System.Drawing.Drawing2D.InterpolationMode), comboBoxInterpolationModes.Items[comboBoxInterpolationModes.SelectedIndex].ToString());
            // set it
            interpolatedPictureBox1.Interpolation = currentState;
        }

        private void changeColorScheme(object sender, EventArgs e)
        {
            var currentScheme = comboBox3.SelectedItem.ToString();

            switch (currentScheme)
            {
                case "Rainbow":
                    m_simulator.TargetColor = Color.YellowGreen;
                    m_simulator.StartColor = Color.DarkRed;
                    break;
                case "Graytones":
                    m_simulator.TargetColor = Color.Black;
                    m_simulator.StartColor = Color.WhiteSmoke;
                    break;
                case "Warm":
                    m_simulator.TargetColor = Color.OrangeRed;
                    m_simulator.StartColor = Color.Yellow;
                    break;
                case "Cold":
                    m_simulator.TargetColor = Color.LightBlue;
                    m_simulator.StartColor = Color.DarkBlue;
                    break;
            }
        }

        private void changeTransparency(object sender, EventArgs e)
        {
            m_simulator.Transparency = checkBox4.Checked;
        }

    }
}
